// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.physics;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import zombie.characters.IsoPlayer;
import zombie.debug.DebugLog;
import zombie.iso.IsoChunk;
import zombie.network.GameServer;
import zombie.network.MPStatistic;
import zombie.vehicles.BaseVehicle;

public class Bullet {
    public static ByteBuffer cmdBuf;
    public static final byte TO_ADD_VEHICLE = 4;
    public static final byte TO_SCROLL_CHUNKMAP = 5;
    public static final byte TO_ACTIVATE_CHUNKMAP = 6;
    public static final byte TO_INIT_WORLD = 7;
    public static final byte TO_UPDATE_CHUNK = 8;
    public static final byte TO_DEBUG_DRAW_WORLD = 9;
    public static final byte TO_STEP_SIMULATION = 10;
    public static final byte TO_UPDATE_PLAYER_LIST = 12;
    public static final byte TO_END = -1;

    public static void init() {
        String string0 = "";
        if ("1".equals(System.getProperty("zomboid.debuglibs.bullet"))) {
            DebugLog.log("***** Loading debug version of PZBullet");
            string0 = "d";
        }

        String string1 = "";
        if (GameServer.bServer && zombie.GameWindow.OSValidator.isUnix()) {
            string1 = "NoOpenGL";
        }

        if (System.getProperty("os.name").contains("OS X")) {
            System.loadLibrary("PZBullet");
        } else if (System.getProperty("sun.arch.data.model").equals("64")) {
            System.loadLibrary("PZBullet" + string1 + "64" + string0);
        } else {
            System.loadLibrary("PZBullet" + string1 + "32" + string0);
        }

        cmdBuf = ByteBuffer.allocateDirect(4096);
        cmdBuf.order(ByteOrder.LITTLE_ENDIAN);
    }

    private static native void ToBullet(ByteBuffer var0);

    public static void CatchToBullet(ByteBuffer bb) {
        try {
            MPStatistic.getInstance().Bullet.Start();
            ToBullet(bb);
            MPStatistic.getInstance().Bullet.End();
        } catch (RuntimeException runtimeException) {
            runtimeException.printStackTrace();
        }
    }

    public static native void initWorld(int offsetX, int offsetY, boolean bServer);

    public static native void destroyWorld();

    public static native void activateChunkMap(int playerIndex, int wx, int wy, int chunkGridWidth);

    public static native void deactivateChunkMap(int playerIndex);

    public static void initWorld(int offsetX, int offsetY, int wx, int wy, int chunkGridWidth) {
        MPStatistic.getInstance().Bullet.Start();
        initWorld(offsetX, offsetY, GameServer.bServer);
        activateChunkMap(0, wx, wy, chunkGridWidth);
        MPStatistic.getInstance().Bullet.End();
    }

    public static void updatePlayerList(ArrayList<IsoPlayer> players) {
        cmdBuf.clear();
        cmdBuf.put((byte)12);
        cmdBuf.putShort((short)players.size());

        for (IsoPlayer isoPlayer : players) {
            cmdBuf.putInt(isoPlayer.OnlineID);
            cmdBuf.putInt((int)isoPlayer.getX());
            cmdBuf.putInt((int)isoPlayer.getY());
        }

        cmdBuf.put((byte)-1);
        cmdBuf.put((byte)-1);
        CatchToBullet(cmdBuf);
    }

    public static void beginUpdateChunk(IsoChunk chunk) {
        cmdBuf.clear();
        cmdBuf.put((byte)8);
        cmdBuf.putShort((short)chunk.wx);
        cmdBuf.putShort((short)chunk.wy);
    }

    public static void updateChunk(int int0, int int1, int int2, int int3, byte[] _byte) {
        cmdBuf.put((byte)int0);
        cmdBuf.put((byte)int1);
        cmdBuf.put((byte)int2);
        cmdBuf.put((byte)int3);

        for (int int4 = 0; int4 < int3; int4++) {
            cmdBuf.put(_byte[int4]);
        }
    }

    public static void endUpdateChunk() {
        if (cmdBuf.position() != 5) {
            cmdBuf.put((byte)-1);
            cmdBuf.put((byte)-1);
            CatchToBullet(cmdBuf);
        }
    }

    public static native void scrollChunkMap(int playerIndex, int dir);

    public static void scrollChunkMapLeft(int playerIndex) {
        MPStatistic.getInstance().Bullet.Start();
        scrollChunkMap(playerIndex, 0);
        MPStatistic.getInstance().Bullet.End();
    }

    public static void scrollChunkMapRight(int playerIndex) {
        MPStatistic.getInstance().Bullet.Start();
        scrollChunkMap(playerIndex, 1);
        MPStatistic.getInstance().Bullet.End();
    }

    public static void scrollChunkMapUp(int playerIndex) {
        MPStatistic.getInstance().Bullet.Start();
        scrollChunkMap(playerIndex, 2);
        MPStatistic.getInstance().Bullet.End();
    }

    public static void scrollChunkMapDown(int playerIndex) {
        MPStatistic.getInstance().Bullet.Start();
        scrollChunkMap(playerIndex, 3);
        MPStatistic.getInstance().Bullet.End();
    }

    public static void setVehicleActive(BaseVehicle vehicle, boolean isActive) {
        vehicle.isActive = isActive;
        setVehicleActive(vehicle.getId(), isActive);
    }

    public static int setVehicleStatic(BaseVehicle vehicle, boolean isStatic) {
        vehicle.isStatic = isStatic;
        return setVehicleStatic(vehicle.getId(), isStatic);
    }

    public static native void addVehicle(int ID, float x, float y, float z, float qx, float qy, float qz, float qw, String scriptName);

    public static native void removeVehicle(int ID);

    public static native void controlVehicle(int ID, float engineForce, float brakeForce, float steerAngle);

    public static native void setVehicleActive(int ID, boolean active);

    public static native void applyCentralForceToVehicle(int ID, float fx, float fy, float fz);

    public static native void applyTorqueToVehicle(int ID, float tx, float ty, float tz);

    public static native void teleportVehicle(int ID, float x, float y, float z, float qx, float qy, float qz, float qw);

    public static native void setTireInflation(int ID, int wheelIndex, float inflation);

    public static native void setTireRemoved(int ID, int wheelIndex, boolean removed);

    public static native void stepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep);

    public static native int getVehicleCount();

    public static native int getVehiclePhysics(int var0, float[] var1);

    public static native int getOwnVehiclePhysics(int var0, float[] var1);

    public static native int setOwnVehiclePhysics(int var0, float[] var1);

    public static native int setVehicleParams(int var0, float[] var1);

    public static native int setVehicleMass(int vid, float mass);

    public static native int getObjectPhysics(float[] var0);

    public static native void createServerCell(int x, int y);

    public static native void removeServerCell(int x, int y);

    public static native int addPhysicsObject(float x, float y);

    public static native void defineVehicleScript(String var0, float[] var1);

    public static native void setVehicleVelocityMultiplier(int vid, float maxSpeed, float multiplier);

    public static native int setVehicleStatic(int vid, boolean isStatic);

    public static native int addHingeConstraint(int vidA, int vidB, float pivotXA, float pivotYA, float pivotZA, float pivotXB, float pivotYB, float pivotZB);

    public static native int addPointConstraint(int vidA, int vidB, float pivotXA, float pivotYA, float pivotZA, float pivotXB, float pivotYB, float pivotZB);

    public static native int addRopeConstraint(
        int vidA, int vidB, float pivotXA, float pivotYA, float pivotZA, float pivotXB, float pivotYB, float pivotZB, float linearLimit
    );

    public static native void removeConstraint(int id);
}
